package com.kangjia.api;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.bson.Document;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.kangjia.api.condition.MongoReportCondition;
import com.kangjia.api.dao.KangjiaMongoDao;
import com.kangjia.holder.TableContextHolder;
import com.kangjia.http.HttpParam;
import com.kangjia.http.HttpResponse;
import com.kangjia.jasckson.DataMapper;
import com.kangjia.model.m0.dao.ReportDao;
import com.kangjia.model.m0.entity.Age;
import com.kangjia.model.m0.entity.PersionPk;
import com.kangjia.model.m0.entity.PersionReport;
import com.kangjia.model.m0.entity.StorePk;
import com.kangjia.model.m0.entity.StoreReport;
import com.kangjia.model.m0.entity.User;
import com.kangjia.model.m0.service.ParseService;
import com.kangjia.util.JsonNodeUtil;

import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/**
 * 报告api接口实现类
 * 
 * @author sunshulin
 *
 */
@Service
@Slf4j
public class ReportApiImpl extends AbstractApiImpl {

	@Value("${kangjia.token.url}")
	private String url;
	@Value("${callback.url}")
	private String call;
	@Autowired
	private KangjiaMongoDao kangjiaMongoDao;
	@Autowired
	private JedisPool jedisPool;
	@Autowired
	private ReportDao reportDao;
	@Autowired
	private ParseService parseService;
	@Autowired
	private RabbitTemplate rabbitTemplate;

	/**
	 * 获取康加报告数据集合
	 * 
	 * @throws IOException
	 * @throws JsonProcessingException
	 */
	public String getReport(Long userId, String reportId, String mobile, String name, Integer age, User user)
			throws JsonProcessingException, IOException {
		String uuid = redis(userId, mobile, name, age);
		String token = getKangjiaToken();
		List<HttpParam> params = new ArrayList<>();
		params.add(new HttpParam("encoding", "utf-8"));
		if (StringUtils.isNotBlank(call)) {
			params.add(new HttpParam("frontUrl", call + "/callback?uuid=" + uuid));
		} else {
			params.add(new HttpParam("frontUrl", ""));
		}
		params.add(new HttpParam("mobile", mobile == null ? "" : mobile));
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		params.add(new HttpParam("reportId", reportId));
		params.add(new HttpParam("reqTime", sdf.format(new Date())));
		params.add(new HttpParam("token", token));
		params.add(new HttpParam("tradeType", "02"));
		params.add(new HttpParam("userId", userId == null ? "" : userId.toString()));
		params.add(new HttpParam("version", "1.0"));
		params.add(new HttpParam("sign", getSign(params)));
		long s = System.currentTimeMillis();
		HttpResponse response = httpRequest.form(url + "getReport", params);
		log.info("查询报告耗时={}", System.currentTimeMillis() - s);
		JsonNode data = handlerResponse(response, "inspectResultBaseInfoView");
		if (data != null) {
			s = System.currentTimeMillis();
			String json = parseService.handlerKpi(data.toString(), age, name, mobile, user);
			log.info("二次生成报告耗时={}", System.currentTimeMillis() - s);
			handlerReport(DataMapper.getInstance().readTree(json), uuid);
			log.info("异步接收报告.");
			try {
				sendRabbitmq(reportId);				
			} catch(Exception e) {
				log.error("rabbitmq异常", e);
			}
			return json;
		} else {
			log.error("请求康加接口getReport出现异常,查看具体日志信息.");
			return null;
		}
	}
	
	/**
	 * 发送信息到mq中
	 * @param userId
	 * @param reportId
	 */
	private void sendRabbitmq(String reportId) {
		MessageProperties properties = new MessageProperties();
		Message message = new Message(reportId.getBytes(), properties);
		rabbitTemplate.send("*.report.*", message);
	}

	/**
	 * 返回报告数据处理
	 * 
	 * @param data
	 */
	public void handlerReport(JsonNode data, String uuid) {
		if (data != null) {
			String inspectId = JsonNodeUtil.string(data, "inspectId");
			String name = get(uuid, "name");
			String mobile = get(uuid, "mobile");
			String userId = get(uuid, "userId");
			String age = get(uuid, "age");
			Long crtime = System.currentTimeMillis();
			Integer total = 0;
			JsonNode j = data.get("totalScore");
			if (!j.isNull()) {
				total = j.asInt();
			}
			PersionReport pr = createPersionReport(inspectId, name, mobile, userId, crtime, total);
			TableContextHolder.mod(TableContextHolder.persion, Long.parseLong(userId), 10L);
			long s = System.currentTimeMillis();
			reportDao.saveOrUpdate(pr);
			StoreReport sr = createStoreReport(inspectId, name, mobile, userId, crtime, total);
			TableContextHolder.mod(TableContextHolder.store, new Long(sr.getStorePk().getStoreId()), 10L);
			reportDao.saveOrUpdate(sr);
			log.info("保存db耗时={}", System.currentTimeMillis() - s);
			s = System.currentTimeMillis();
			createAge(new Long(userId), age, data);
			log.info("保存db age耗时={}", System.currentTimeMillis() - s);
			s = System.currentTimeMillis();
			mongo(data, inspectId);
			log.info("保存mogo耗时={}", System.currentTimeMillis() - s);
		} else {
			log.error("请求康加接口getReport出现异常,查看具体日志信息.");
		}
	}

	private void createAge(Long uid, String age, JsonNode data) {
		Integer totalScore = 0;
		if (!data.get("totalScore").isNull()) {
			totalScore = data.get("totalScore").asInt();
		}
		LocalDate ld = LocalDate.now();
		Age entity = new Age();
		entity.setMobile(uid);
		entity.setAge(new Integer(age));
		entity.setScore(totalScore);
		entity.setReportId(JsonNodeUtil.string(data, "inspectId"));
		entity.setLastTime(new Long(ld.getYear() + "" + String.format("%02d", ld.getMonthValue()) + "" + String.format("%02d", ld.getDayOfMonth())));
		reportDao.saveOrUpdate(entity);
	}

	private void mongo(JsonNode data, String inspectId) {
		MongoReportCondition mrc = new MongoReportCondition(inspectId);
		Document document = kangjiaMongoDao.findOne(mrc);
		if (document != null) {
			kangjiaMongoDao.updateData(data, inspectId);
		} else {
			kangjiaMongoDao.saveData(data, inspectId);
		}
	}

	public String getReport(String inspectId) {
		MongoReportCondition mrc = new MongoReportCondition(inspectId);
		Document document = kangjiaMongoDao.findOne(mrc);
		if (document != null) {			
			return document.toJson();
		} else {
			return null;
		}
	}

	private PersionReport createPersionReport(String inspectId, String name, String mobile, String userId,
			Long crtime, Integer total) {
		PersionPk persionPk = new PersionPk();
		persionPk.setInspectId(inspectId);
		persionPk.setMobile(mobile);
		persionPk.setUserId(userId);
		PersionReport pr = new PersionReport();
		pr.setCrtime(crtime);
		pr.setName(name);
		pr.setPersionPk(persionPk);
		pr.setScore(total);
		return pr;
	}

	private StoreReport createStoreReport(String inspectId, String name, String mobile, String userId, Long crtime, Integer total) {
		StorePk storePk = new StorePk();
		storePk.setInspectId(inspectId);
		Integer storeId = -1;
		String sn = inspectId.substring(0, 17);
		String json = get("device", inspectId.substring(0, 17));
		if (StringUtils.isNotBlank(json)) {
			JsonNode jsonNode;
			try {
				jsonNode = DataMapper.getInstance().readTree(json);
				storeId = JsonNodeUtil.integer(jsonNode, "storeId");
			} catch (JsonProcessingException e) {
				log.error("json processing exception", e);
			} catch (IOException e) {
				log.error("io exception", e);
			}
		}
		storePk.setStoreId(storeId);
		StoreReport sr = new StoreReport();
		sr.setCrtime(crtime);
		sr.setMobile(mobile);
		sr.setName(name);
		sr.setUserId(userId);
		sr.setStorePk(storePk);
		sr.setSn(sn);
		sr.setPhone(mobile);
		sr.setScore(total);
		return sr;
	}

	private String redis(Long userId, String mobile, String name, Integer age) {
		String uuid = UUID.randomUUID().toString().replace("-", "");
		Jedis jedis = jedisPool.getResource();
		try {
			jedis.hset(uuid, "userId", userId.toString());
			jedis.hset(uuid, "mobile", StringUtils.isBlank(mobile) ? "" : mobile);
			jedis.hset(uuid, "name", StringUtils.isBlank(name) ? "" : name);
			jedis.hset(uuid, "age", age == null ? "0" : age.toString());
			jedis.expire(uuid, 3600);
		} finally {
			jedis.close();
		}
		return uuid;
	}

	public String get(String key, String field) {
		Jedis jedis = jedisPool.getResource();
		try {
			return jedis.hget(key, field);
		} finally {
			jedis.close();
		}
	}

}
